/*****************************************************************************
 * $LastChangedDate: 2009-12-28 22:35:38 -0500 (Mon, 28 Dec 2009) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   Functions to clamp values.
 * @remarks This remains in the base module (not math) since Clamp() is used for Array2D.
 *//*
 * LEGAL:   COPYRIGHT (C) 2004 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

#ifndef BASE_CLAMP_HH
#define BASE_CLAMP_HH 1

namespace base {

/*****************************************************************************
 * Clamp SIGNED number in range {0,...,limit} inclusive.
 * For unsigned numbers, use MAX(limit) which is faster.
 *****************************************************************************/
template<typename SIGNED>
SIGNED
Clamp( const SIGNED n, const SIGNED limit )
{
    if ( UX( n <= 0 ) )
        return 0;
    else if ( UX( n >= limit ) )
        return limit;
    else
        return n;
}

/*****************************************************************************
 * Clamp number to range {low,..,high} inclusive.
 *****************************************************************************/
template<typename T>
T
Clamp( const T n, const T low, const T high )
{
ASSERT( low < high );

    if ( UX( n <= low ) )
        return low;
    else if ( UX( n >= high ) )
        return high;
    else
        return n;
}

/*****************************************************************************
 * Clamp fp to within range {0.0,...,1.0} inclusive.
 *****************************************************************************/
INLINE fp
Clamp1( const fp f )
{
    if ( UX( f <= 0.0f ) )
        return 0.0f;
    else if ( UX( f >= 1.0f ) )
        return 1.0f;
    else
        return f;
}

/*****************************************************************************
 * Clamp number to 8-bit range {0x00,..,0xff}.
 * ClampFF(uint) is the fastest.
 *****************************************************************************/
INLINE uint8
ClampFF( const uint ui )
{
    // gcc 4 optimally compiles an x86 CMOV instruction.
    if ( EX(ui <= 0xff) )
        return uint8(ui);
    else
        return 0xff;
}

INLINE uint8
ClampFF( const int i )
{
    if ( UX( i <= 0 ) )
        return 0;
    else if ( UX( i >= 0xff ) )
        return 0xff;
    else
        return uint8(i);
}

INLINE uint8
ClampFF( const fp f )
{
    if ( UX( f <= 0.0f ) )
        return 0;
    else if ( UX( f >= 1.0f ) )
        return 0xff;
    else
        return uint8( f * 255.0f );  // 0xff
}

} // namespace base

#endif // BASE_CLAMP_HH
